using System;
using HybridCLR;
using System.Collections;
using System.Collections.Generic;
using GameMain.Scripts;
using HotFix.Utils;
using UnityEngine;
using Debug = UnityEngine.Debug;
using Object = UnityEngine.Object;

namespace HotFix
{
    public class App
    {
        private static unsafe void LoadMetadataForAotAssembly(Dictionary<string, byte[]> dllBytes)
        {
#if !UNITY_EDITOR
            dllBytes ??= new Dictionary<string, byte[]>();

            Debug.Log($"[App::LoadMetadataForAotAssembly] Count:{dllBytes.Count}");
            foreach (var dll in dllBytes)
            {
                Debug.Log($"[App::LoadMetadataForAotAssembly] load {dll.Key}");

                fixed (byte* ptr = dll.Value)
                {
                    var iPtr = (IntPtr) ptr;
                    var len = dll.Value.Length;
                    try
                    {
                        var err = (LoadImageErrorCode) RuntimeApi.LoadMetadataForAOTAssembly(iPtr, len);
                        if (err != LoadImageErrorCode.OK)
                        {
                            Debug.Log($"[App::LoadMetadataForAotAssembly] load {dll.Key} ret:{err}");
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.Log($"[App::LoadMetadataForAotAssembly] load {dll.Key} exception");
                        Debug.LogException(ex);
                    }
                }
            }

            Debug.Log($"[App::LoadMetadataForAotAssembly] finished!");
#endif
        }

        private static IEnumerator RunLua(Action callbcak)
        {
            Debug.Log($"[App::RunLua]");
#if !UNITY_EDITOR
            yield return GameRoot.Instance.LoadData("base.bytes", "base", LoadMetadataForAotAssembly);
#endif
            LuaCache.Clear();
            Debug.Log($"[App::RunLua] LuaEnvUtil.Reset");
            if (LuaEnvUtil.Global == null)
            {
                LuaEnvUtil.Reset("", null);
            }

            yield return GameRoot.Instance.LoadData("lua.bytes", "lua", scripts =>
            {
                scripts ??= new Dictionary<string, byte[]>();
                foreach (var kv in scripts)
                {
                    LuaCache.Set(kv.Key, kv.Value);
                }
            });

            var code = LuaCache.Get("Launcher.lua.txt");
            if (code == null)
            {
                Debug.Log($"[App::RunLua] code is empty");
                yield break;
            }

            LuaEnvUtil.DoString(code);

            callbcak?.Invoke();
        }

        public static void Main()
        {
            Debug.Log("[App::Main] Begin");

            var go = new GameObject("HotFixMain");
            Object.DontDestroyOnLoad(go);



            GameRoot.Instance.StartCoroutine(RunLua(() => { Debug.Log("[App::Main] End"); }));
        }
    }
}
